/**
 * 水滴特效指令
 * install function
 * @param  {Vue} Vue 对象
 * @param  {object} options 水滴特效设置
 */
export default {
  install (Vue) {
    Vue.directive('ripple', {
      inserted: function (el, { value }) {
        if (value) addEvent(el)
      },
      update: function (el, { value }) {
        value ? addEvent(el) : removeEvent(el)
      },
      unbind: function (el, { value }) {
        if (value) removeEvent(el)
      }
    })
  }
}
function addEvent (el) {
  el.addEventListener('mousedown', createRipple)
  el.addEventListener('mouseup', removeRipple)
}
function removeEvent (el) {
  el.removeEventListener('mousedown', createRipple)
  el.removeEventListener('mouseup', removeRipple)
}

function createRipple (event) {
  const container = event.target
  const { x, y, centerX, centerY, size } = computeRippleStyles(container, event)
  const ripple = document.createElement('div')
  ripple.classList.add('bk-ripple')
  ripple.style.opacity = `0`
  ripple.style.transform = `translate(${x}px, ${y}px) scale3d(.3, .3, .3)`
  ripple.style.width = `${size}px`
  ripple.style.height = `${size}px`
  // 记录水波的创建时间
  ripple.dataset.createdAt = String(performance.now())

  const { position } = window.getComputedStyle(container)
  container.style.overflow = 'hidden'
  position === 'static' && (container.style.position = 'relative')

  container.appendChild(ripple)

  window.setTimeout(() => {
    ripple.style.transform = `translate(${centerX}px, ${centerY}px) scale3d(1, 1, 1)`
    ripple.style.opacity = `.25`
  })
}
function removeRipple (event) {
  const container = event.target
  const ripples = container.querySelectorAll('.bk-ripple')
  if (!ripples.length) return

  const lastRipple = ripples[ripples.length - 1]
  // 通过水波的创建时间计算出扩散动画还需要执行多久，确保每一个水波都完整的执行了扩散动画
  const delay = 300 - performance.now() + Number(lastRipple.dataset.createdAt)

  setTimeout(() => {
    lastRipple.style.opacity = `0`
    setTimeout(() => {
      if (lastRipple.parentNode) {
        lastRipple.parentNode.removeChild(lastRipple)
      }
    }, 300)
  }, delay)
}
function computeRippleStyles (element, event) {
  const { top, left } = element.getBoundingClientRect()
  const { clientWidth, clientHeight } = element

  const radius = Math.sqrt(clientWidth ** 2 + clientHeight ** 2) / 2
  const size = radius * 2

  const localX = event.clientX - left
  const localY = event.clientY - top

  const centerX = (clientWidth - radius * 2) / 2
  const centerY = (clientHeight - radius * 2) / 2

  const x = localX - radius
  const y = localY - radius

  return { x, y, centerX, centerY, size }
}
